package fw.helpers;

import static fw.Config.WEBDRIVER_WAIT;

import java.util.List;

import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.Select;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import fw.ApplicationManager;

public class WebElementFinderHelper {
	private final ApplicationManager app;
	private static Logger LOG = LoggerFactory.getLogger(WebElementFinderHelper.class);

	/**
	 * Constructor
	 * 
	 * @param app
	 */
	public WebElementFinderHelper(ApplicationManager app) {
		this.app = app;
	}

	/**
	 * Find web element by locator name
	 * 
	 * @param webElement
	 * @param locator
	 * @return
	 */
	public WebElement findStatic(WebElement webElement, By locator) {
		return findStatic(webElement, locator, 1);
	}

	/**
	 * 
	 * @param webElement
	 * @param locator
	 * @return
	 */
	public WebElement findStatic(WebElement webElement, By locator, int waitFactor) {
		if (webElement == null) {
			webElement = findDynamic(locator, waitFactor);
		}
		return webElement;
	}

	/**
	 * Find web element by locator chain
	 * 
	 * @param webElement
	 * @param locators
	 * @return
	 */
	public WebElement findStatic(WebElement webElement, String[] locators) {
		if (webElement == null) {
			webElement = findDynamic(getXpathChainLocator(locators));
		}
		return webElement;
	}

	/**
	 * Find select by locator name
	 * 
	 * @param webElement
	 * @param locator
	 * @return
	 */
	public Select findSelectStatic(Select webElement, By locator) {
		if (webElement == null) {
			webElement = findSelectDynamic(locator, 1);
		}
		return webElement;
	}

	public Select findSelectDynamic(By locator, int waitFactor) {
		Select selectElement = null;
		try {
			selectElement = new Select(findDynamic(locator, waitFactor));
		} catch (Exception ex) {
			LOG.warn("Web element not found: " + locator);
		}
		return selectElement;
	}

	public WebElement findDynamic(String[] locators) {
		return findDynamic(getXpathChainLocator(locators), 1);
	}

	public WebElement findDynamic(String[] locators, int waitFactor) {
		return findDynamic(getXpathChainLocator(locators), waitFactor);
	}

	public List<WebElement> findDynamicList(String[] locators, int waitFactor) {
		return findDynamicList(getXpathChainLocator(locators), waitFactor);
	}

	public List<WebElement> findDynamicList(String[] locators) {
		return findDynamicList(getXpathChainLocator(locators), 1);
	}

	public List<WebElement> findDynamicList(By locator) {
		return findDynamicList(locator, 1);
	}

	public WebElement findDynamic(By locator) {
		return findDynamic(locator, 1);
	}

	private WebElement findDynamic(By locator, int waitFactor) {
		LOG.debug("Find element: " + locator);

		WebDriverWait wait = null;
		WebElement webElement = null;

		wait = setWaitTime(WEBDRIVER_WAIT * waitFactor);
		if (locator != null) {
			try {
				webElement = wait.until(ExpectedConditions.presenceOfElementLocated(locator));
				LOG.debug("Find element: " + locator + " => true");
			} catch (Exception ex) {
				LOG.warn("Web element not found: " + locator);
			}
		}
		return webElement;
	}

	public List<WebElement> findDynamicList(By locator, int waitFactor) {
		LOG.debug("Find element: " + locator);

		WebDriverWait wait = null;
		List<WebElement> webElements = null;
		wait = setWaitTime(waitFactor);
		if (locator != null) {
			try {
				webElements = wait.until(ExpectedConditions.presenceOfAllElementsLocatedBy(locator));
				LOG.debug("Find element: " + locator + " => true");
			} catch (Exception ex) {
				LOG.warn("Web element not found: " + locator);
			}
		}
		return webElements;
	}

	private WebDriverWait setWaitTime(int waitFactor) {
		WebDriverWait wait;
		if (waitFactor != 0) {
			wait = new WebDriverWait(app.getDriver(), waitFactor);
		} else {
			wait = app.wait;
		}
		return wait;
	}

	public By getXpathChainLocator(String[] parts) {
		String r_locatorValue = "";
		for (String part : parts) {
			r_locatorValue += part;
		}
		return By.xpath(r_locatorValue);
	}

	public String getXPathToJsStyle(String[] parts) {
		String r_locatorValue = "";

		for (String part : parts) {
			r_locatorValue += part;
		}
		r_locatorValue = r_locatorValue.replaceAll("@", "");
		String r_XPath = "\"" + r_locatorValue + "\"";

		return r_XPath;
	}

	public String getCssToJsStyle(String[] parts) {
		String r_locatorValue = "";

		for (String part : parts) {
			r_locatorValue += part;
		}

		String r_Css = r_locatorValue;

		return r_Css;
	}
}
